﻿using System;
using System.IO;
using System.Xml;
using System.Text;

namespace Narwhunderful.Aphelia.Framework.IO.Serialization.Xml
{

    public sealed class DefaultXmlWriter : IXmlWriter
    {
        private readonly XmlWriterSettings _settings;
        private readonly ISimpleValueConverter _simpleValueConverter;
        private readonly ITypeNameConverter _typeNameProvider;

        private XmlWriter _writer;

        public DefaultXmlWriter(ITypeNameConverter typeNameProvider, ISimpleValueConverter simpleValueConverter, XmlWriterSettings settings)
        {
            if (typeNameProvider == null) throw new ArgumentNullException("typeNameProvider");
            if (simpleValueConverter == null) throw new ArgumentNullException("simpleValueConverter");
            if (settings == null) throw new ArgumentNullException("settings");

            _simpleValueConverter = simpleValueConverter;
            _settings = settings;
            _typeNameProvider = typeNameProvider;
        }

        public void WriteStartElement(string elementId)
        {
            _writer.WriteStartElement(elementId);
        }

        public void WriteEndElement()
        {
            _writer.WriteEndElement();
        }

        public void WriteAttribute(string attributeId, string text)
        {
            if (text == null) return;
            _writer.WriteAttributeString(attributeId, text);
        }

        public void WriteAttribute(string attributeId, Type type)
        {
            if (type == null) return;
            string valueAsText = _typeNameProvider.ConvertToTypeName(type);
            WriteAttribute(attributeId, valueAsText);
        }

        public void WriteAttribute(string attributeId, int number)
        {
            _writer.WriteAttributeString(attributeId, number.ToString());
        }

        public void WriteAttribute(string attributeId, int[] numbers)
        {
            string valueAsText = getArrayOfIntAsText(numbers);
            _writer.WriteAttributeString(attributeId, valueAsText);
        }

        public void WriteAttribute(string attributeId, object value)
        {
            if (value == null) return;
            string valueAsText = _simpleValueConverter.ConvertToString(value);
            _writer.WriteAttributeString(attributeId, valueAsText);
        }

        public void Open(Stream stream)
        {
            _writer = XmlWriter.Create(stream, _settings);

            _writer.WriteStartDocument(true);
        }

        public void Close()
        {
            _writer.WriteEndDocument();
            _writer.Close();
        }

        private static string getArrayOfIntAsText(int[] values)
        {
            if (values.Length == 0) return string.Empty;
            var sb = new StringBuilder();
            foreach (int index in values)
            {
                sb.Append(index.ToString());
                sb.Append(",");
            }
            string result = sb.ToString().TrimEnd(new[] { ',' });
            return result;
        }

    }

}
